use std::io;

use thiserror::Error;

#[derive(Debug, Error)]
pub enum Error {
    #[error("not configured as device")]
    NotDevice,

    #[error("datadir: {0}")]
    Datadir(#[from] aspect_core::datadir::Error),

    #[error("ident: {0}")]
    Identity(#[from] aspect_ident::errors::Error),

    #[error("protocol: {0}")]
    ProtoClient(#[from] aspect_proto::core::AspClientError),

    #[error("codec: {0}")]
    Codec(#[from] aspect_codec::CodecError),

    #[error("hex: {0}")]
    Hex(#[from] hex::FromHexError),

    #[error("io: {0}")]
    Io(#[from] io::Error),

    #[error("unimplemented")]
    Unimplemented,

    #[error("{0}")]
    Other(String),
}

impl Error {
    pub fn exitcode(&self) -> u8 {
        match self {
            Self::NotDevice => 0x80,
            Self::Datadir(_) => 1,
            Self::Identity(_) => 2,
            Self::ProtoClient(_) => 3,
            Self::Codec(_) => 0xf0,
            Self::Hex(_) => 0xf1,
            Self::Io(_) => 0xf2,
            Self::Unimplemented => 0xfe,
            Self::Other(_) => 0xff,
        }
    }
}
